package com.itheima.reggie.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.common.BaseContext;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.mapper.OrdersMapper;
import com.itheima.reggie.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private UserService userService;

    @Autowired
    private AddressBookService addressBookService;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private DishService dishService;

    @Autowired
    private SetmealService setmealService;

    @Autowired
    private HttpSession session;
    @Override
    @Transactional
    public List<OrderDetail> submit(Orders orders) {
        Long userId = (Long) session.getAttribute("user");

        User user = userService.getById(userId);

        LambdaQueryWrapper<ShoppingCart> shoppingCartLqw = new LambdaQueryWrapper<>();
        shoppingCartLqw.eq(ShoppingCart::getUserId,userId);
        List<ShoppingCart> shoppingCartList = shoppingCartService.list(shoppingCartLqw);

        if (shoppingCartList == null || shoppingCartList.size() == 0){
            throw new CustomException("购物车为空，不能下单");
        }

        LambdaQueryWrapper<AddressBook> addressBookLqw = new LambdaQueryWrapper<>();
        addressBookLqw.eq(AddressBook::getId,orders.getAddressBookId());
        AddressBook addressBook = addressBookService.getOne(addressBookLqw);
        if (addressBook == null){
            throw new CustomException("地址为空，不能下单");
        }

        long orderId = IdWorker.getId();
        AtomicInteger amount = new AtomicInteger(0);

        List<OrderDetail> orderDetailList = shoppingCartList.stream().map(item -> {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(item, orderDetail);
            orderDetail.setId(null);
            orderDetail.setOrderId(orderId);
            BigDecimal itemAmount = item.getAmount();
            Integer itemNumber = item.getNumber();
            amount.addAndGet(itemAmount.multiply(new BigDecimal(itemNumber)).intValue());
            return orderDetail;
        }).collect(Collectors.toList());

        orders.setId(orderId);
        orders.setAmount(new BigDecimal(amount.get()));
        orders.setUserId(userId);
        orders.setOrderTime(LocalDateTime.now());
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setNumber(String.valueOf(orderId));
        orders.setStatus(2);
        orders.setUserName(user.getName());
        orders.setPhone(addressBook.getPhone());
        orders.setConsignee(addressBook.getConsignee());
        orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
                + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));

        save(orders);
        orderDetailService.saveBatch(orderDetailList);
        shoppingCartService.remove(shoppingCartLqw);
        return orderDetailList;
    }

    @Override
    public void again(Orders order) {
        LambdaQueryWrapper<ShoppingCart> lqw = new LambdaQueryWrapper<>();
        Long userId = (Long) session.getAttribute("user");
        lqw.eq(ShoppingCart::getUserId,userId);
        shoppingCartService.remove(lqw);

        LambdaQueryWrapper<OrderDetail> orderDetailLqw = new LambdaQueryWrapper<>();
        orderDetailLqw.eq(OrderDetail::getOrderId,order.getId());
        List<OrderDetail> list = orderDetailService.list(orderDetailLqw);

        ArrayList<ShoppingCart> shoppingCarts = new ArrayList<>();
        list.stream().forEach(item -> {
            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(item,shoppingCart);
            shoppingCart.setUserId(userId);
            shoppingCarts.add(shoppingCart);
        });

        shoppingCartService.saveBatch(shoppingCarts);
    }

    @Override
    @CacheEvict(value = "dishCache",allEntries = true)
    public void updateDishSort(List<OrderDetail> orderDetails) {
        Map<Long, Integer> dishMap = orderDetails.stream().filter(item -> item.getDishId() != null).collect(Collectors.toMap(OrderDetail::getDishId, OrderDetail::getNumber));
        Set<Map.Entry<Long, Integer>> dishEntries = dishMap.entrySet();
        for (Map.Entry<Long, Integer> dishEntry : dishEntries) {
            Dish dish = dishService.getById(dishEntry.getKey());
            dish.setSort(dish.getSort()+dishEntry.getValue());
            dishService.updateById(dish);
        }
    }

    @Override
    @CacheEvict(value = "setmealCache",allEntries = true)
    public void updateSetmealCode(List<OrderDetail> orderDetails) {
        Map<Long, Integer> setmealMap = orderDetails.stream().filter(item -> item.getSetmealId() != null).collect(Collectors.toMap(OrderDetail::getSetmealId, OrderDetail::getNumber));

        Set<Map.Entry<Long, Integer>> setmealEntries = setmealMap.entrySet();
        for (Map.Entry<Long, Integer> setmealEntry : setmealEntries) {
            Setmeal setmeal = setmealService.getById(setmealEntry.getKey());
            int i = Integer.parseInt(setmeal.getCode());
            int codeInt = i + setmealEntry.getValue();
            setmeal.setCode(codeInt+"");
            setmealService.updateById(setmeal);
        }
    }
}
